home *** CD-ROM | disk | FTP | other *** search
/ Technotools / Technotools (Chestnut CD-ROM)(1993).ISO / unix / xyzmodem / zm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-07-16  |  12.8 KB  |  708 lines

  1. /*
  2.  *   Z M . C
  3.  *    ZMODEM protocol primitives
  4.  *    04-16-87  Chuck Forsberg Omen Technology Inc
  5.  *
  6.  * Entry point Functions:
  7.  *    zsbhdr(type, hdr) send binary header
  8.  *    zshhdr(type, hdr) send hex header
  9.  *    zgethdr(hdr, eflag) receive header - binary or hex
  10.  *    zsdata(buf, len, frameend) send data
  11.  *    zrdata(buf, len) receive data
  12.  *    stohdr(pos) store position data in Txhdr
  13.  *    long rclhdr(hdr) recover position offset from header
  14.  */
  15.  
  16. #ifndef CANFDX
  17. #include "zmodem.h"
  18. int Rxtimeout = 100;        /* Tenths of seconds to wait for something */
  19. #endif
  20.  
  21. static char *frametypes[] = {
  22.     "Carrier Lost",        /* -3 */
  23.     "TIMEOUT",        /* -2 */
  24.     "ERROR",        /* -1 */
  25. #define FTOFFSET 3
  26.     "ZRQINIT",
  27.     "ZRINIT",
  28.     "ZSINIT",
  29.     "ZACK",
  30.     "ZFILE",
  31.     "ZSKIP",
  32.     "ZNAK",
  33.     "ZABORT",
  34.     "ZFIN",
  35.     "ZRPOS",
  36.     "ZDATA",
  37.     "ZEOF",
  38.     "ZFERR",
  39.     "ZCRC",
  40.     "ZCHALLENGE",
  41.     "ZCOMPL",
  42.     "ZCAN",
  43.     "ZFREECNT",
  44.     "ZCOMMAND",
  45.     "ZSTDERR",
  46.     "xxxxx"
  47. #define FRTYPES 22    /* Total number of frame types in this array */
  48.             /*  not including psuedo negative entries */
  49. };
  50.  
  51. /* Send ZMODEM binary header hdr of type type */
  52. zsbhdr(type, hdr)
  53. register char *hdr;
  54. {
  55.     register n;
  56.     register unsigned short crc;
  57.  
  58.     vfile("zsbhdr: %s %lx", frametypes[type+FTOFFSET], rclhdr(hdr));
  59.     if (type == ZDATA)
  60.         for (n = Znulls; --n >=0; )
  61.             zsendline(0);
  62.  
  63.     xsendline(ZPAD); xsendline(ZDLE);
  64.  
  65.     if (Crc32t=Txfcs32)
  66.         zsbh32(hdr, type);
  67.     else {
  68.         xsendline(ZBIN); zsendline(type); crc = updcrc(type, 0);
  69.  
  70.         for (n=4; --n >= 0; ++hdr) {
  71.             zsendline(*hdr);
  72.             crc = updcrc((0377& *hdr), crc);
  73.         }
  74.         crc = updcrc(0,updcrc(0,crc));
  75.         zsendline(crc>>8);
  76.         zsendline(crc);
  77.     }
  78.     if (type != ZDATA)
  79.         flushmo();
  80. }
  81.  
  82.  
  83. /* Send ZMODEM binary header hdr of type type */
  84. zsbh32(hdr, type)
  85. register char *hdr;
  86. {
  87.     register n;
  88.     register long crc;
  89.  
  90.     xsendline(ZBIN32);  zsendline(type);
  91.     crc = 0xFFFFFFFFL; crc = UPDC32(type, crc);
  92.  
  93.     for (n=4; --n >= 0; ++hdr) {
  94.         crc = UPDC32((0377 & *hdr), crc);
  95.         zsendline(*hdr);
  96.     }
  97.     crc = ~crc;
  98.     for (n=4; --n >= 0;) {
  99.         zsendline((int)crc);
  100.         crc >>= 8;
  101.     }
  102. }
  103.  
  104. /* Send ZMODEM HEX header hdr of type type */
  105. zshhdr(type, hdr)
  106. register char *hdr;
  107. {
  108.     register n;
  109.     register unsigned short crc;
  110.  
  111.     vfile("zshhdr: %s %lx", frametypes[type+FTOFFSET], rclhdr(hdr));
  112.     sendline(ZPAD); sendline(ZPAD); sendline(ZDLE); sendline(ZHEX);
  113.     zputhex(type);
  114.     Crc32t = 0;
  115.  
  116.     crc = updcrc(type, 0);
  117.     for (n=4; --n >= 0; ++hdr) {
  118.         zputhex(*hdr); crc = updcrc((0377 & *hdr), crc);
  119.     }
  120.     crc = updcrc(0,updcrc(0,crc));
  121.     zputhex(crc>>8); zputhex(crc);
  122.  
  123.     /* Make it printable on remote machine */
  124.     sendline(015); sendline(012);
  125.     /*
  126.      * Uncork the remote in case a fake XOFF has stopped data flow
  127.      */
  128.     if (type != ZFIN && type != ZACK)
  129.         sendline(021);
  130.     flushmo();
  131. }
  132.  
  133. /*
  134.  * Send binary array buf of length length, with ending ZDLE sequence frameend
  135.  */
  136. zsdata(buf, length, frameend)
  137. register char *buf;
  138. {
  139.     register unsigned short crc;
  140.  
  141.     vfile("zsdata: length=%d end=%x", length, frameend);
  142.     if (Crc32t)
  143.         zsda32(buf, length, frameend);
  144.     else {
  145.         crc = 0;
  146.         for (;--length >= 0; ++buf) {
  147.             zsendline(*buf); crc = updcrc((0377 & *buf), crc);
  148.         }
  149.         xsendline(ZDLE); xsendline(frameend);
  150.         crc = updcrc(frameend, crc);
  151.  
  152.         crc = updcrc(0,updcrc(0,crc));
  153.         zsendline(crc>>8); zsendline(crc);
  154.     }
  155.     if (frameend == ZCRCW) {
  156.         xsendline(XON);  flushmo();
  157.     }
  158. }
  159.  
  160. zsda32(buf, length, frameend)
  161. register char *buf;
  162. {
  163.     register long crc;
  164.  
  165.     crc = 0xFFFFFFFFL;
  166.     for (;--length >= 0;++buf) {
  167.         crc = UPDC32((0377 & *buf), crc);
  168.         zsendline(*buf);
  169.     }
  170.     xsendline(ZDLE); xsendline(frameend);
  171.     crc = UPDC32(frameend, crc);
  172.  
  173.     crc = ~crc;
  174.     for (length=4; --length >= 0;) {
  175.         zsendline((int)crc);  crc >>= 8;
  176.     }
  177. }
  178.  
  179. /*
  180.  * Receive array buf of max length with ending ZDLE sequence
  181.  *  and CRC.  Returns the ending character or error code.
  182.  */
  183. zrdata(buf, length)
  184. register char *buf;
  185. {
  186.     register c;
  187.     register unsigned short crc;
  188.     register d;
  189.  
  190.     if (Rxframeind == ZBIN32)
  191.         return zrdat32(buf, length);
  192.  
  193.     crc = Rxcount = 0;
  194.     for (;; ++buf) {
  195.         if ((c = zdlread()) & ~0377) {
  196. crcfoo:
  197.             switch (c) {
  198.             case GOTCRCE:
  199.             case GOTCRCG:
  200.             case GOTCRCQ:
  201.             case GOTCRCW:
  202.                 crc = updcrc((d=c)&0377, crc);
  203.                 if ((c = zdlread()) & ~0377)
  204.                     goto crcfoo;
  205.                 crc = updcrc(c, crc);
  206.                 if ((c = zdlread()) & ~0377)
  207.                     goto crcfoo;
  208.                 crc = updcrc(c, crc);
  209.                 if (crc & 0xFFFF) {
  210.                     zperr("Bad data CRC %x", crc);
  211.                     return ERROR;
  212.                 }
  213.                 vfile("zrdata: cnt = %d ret = %x", Rxcount, d);
  214.                 return d;
  215.             case GOTCAN:
  216.                 zperr("ZMODEM: Sender Canceled");
  217.                 return ZCAN;
  218.             case TIMEOUT:
  219.                 zperr("ZMODEM data TIMEOUT");
  220.                 return c;
  221.             default:
  222.                 zperr("ZMODEM bad data subpacket ret=%x", c);
  223.                 return c;
  224.             }
  225.         }
  226.         if (--length < 0) {
  227.             zperr("ZMODEM data subpacket too long");
  228.             return ERROR;
  229.         }
  230.         ++Rxcount;
  231.         *buf = c;
  232.         crc = updcrc(c, crc);
  233.     }
  234. }
  235.  
  236. zrdat32(buf, length)
  237. register char *buf;
  238. {
  239.     register c;
  240.     register long crc;
  241.     register d;
  242.  
  243.     crc = 0xFFFFFFFFL;  Rxcount = 0;
  244.     for (;; ++buf) {
  245.         if ((c = zdlread()) & ~0377) {
  246. crcfoo:
  247.             switch (c) {
  248.             case GOTCRCE:
  249.             case GOTCRCG:
  250.             case GOTCRCQ:
  251.             case GOTCRCW:
  252.                 d = c;  c &= 0377;
  253.                 crc = UPDC32(c, crc);
  254.                 if ((c = zdlread()) & ~0377)
  255.                     goto crcfoo;
  256.                 crc = UPDC32(c, crc);
  257.                 if ((c = zdlread()) & ~0377)
  258.                     goto crcfoo;
  259.                 crc = UPDC32(c, crc);
  260.                 if ((c = zdlread()) & ~0377)
  261.                     goto crcfoo;
  262.                 crc = UPDC32(c, crc);
  263.                 if ((c = zdlread()) & ~0377)
  264.                     goto crcfoo;
  265.                 crc = UPDC32(c, crc);
  266.                 if (crc != 0xDEBB20E3) {
  267.                     zperr("Bad data CRC %lX", crc);
  268.                     return ERROR;
  269.                 }
  270.                 vfile("zrdat32: cnt = %d ret = %x", Rxcount, d);
  271.                 return d;
  272.             case GOTCAN:
  273.                 zperr("ZMODEM: Sender Canceled");
  274.                 return ZCAN;
  275.             case TIMEOUT:
  276.                 zperr("ZMODEM data TIMEOUT");
  277.                 return c;
  278.             default:
  279.                 zperr("ZMODEM bad data subpacket ret=%x", c);
  280.                 return c;
  281.             }
  282.         }
  283.         if (--length < 0) {
  284.             zperr("ZMODEM data subpacket too long");
  285.             return ERROR;
  286.         }
  287.         ++Rxcount;
  288.         *buf = c;
  289.         crc = UPDC32(c, crc);
  290.     }
  291. }
  292.  
  293.  
  294. /*
  295.  * Read a ZMODEM header to hdr, either binary or hex.
  296.  *  eflag controls local display of non zmodem characters:
  297.  *    0:  no display
  298.  *    1:  display printing characters only
  299.  *    2:  display all non ZMODEM characters
  300.  *  On success, set Zmodem to 1, set Rxpos and return type of header.
  301.  *   Otherwise return negative on error
  302.  */
  303. zgethdr(hdr, eflag)
  304. char *hdr;
  305. {
  306.     register c, n, cancount;
  307.  
  308.     n = Zrwindow + Baudrate;    /* Max bytes before start of frame */
  309.     cancount = 5;
  310.  
  311. again:
  312.     Rxframeind = Rxtype = 0;
  313.     switch (c = noxrd7()) {
  314.     case RCDO:
  315.     case TIMEOUT:
  316.         goto fifi;
  317.     case CAN:
  318.         if (--cancount <= 0) {
  319.             c = ZCAN; goto fifi;
  320.         }
  321.     /* **** FALL THRU TO **** */
  322.     default:
  323. agn2:
  324.         if ( --n == 0) {
  325.             zperr("ZMODEM Garbage count exceeded");
  326.             return(ERROR);
  327.         }
  328.         if (eflag && ((c &= 0177) & 0140))
  329.             bttyout(c);
  330.         else if (eflag > 1)
  331.             bttyout(c);
  332.         if (c != CAN)
  333.             cancount = 5;
  334.         goto again;
  335.     case ZPAD:        /* This is what we want. */
  336.         break;
  337.     }
  338.     cancount = 5;
  339. splat:
  340.     switch (c = noxrd7()) {
  341.     case ZPAD:
  342.         goto splat;
  343.     case RCDO:
  344.     case TIMEOUT:
  345.         goto fifi;
  346.     default:
  347.         goto agn2;
  348.     case ZDLE:        /* This is what we want. */
  349.         break;
  350.     }
  351.  
  352.     switch (c = noxrd7()) {
  353.     case RCDO:
  354.     case TIMEOUT:
  355.         goto fifi;
  356.     case ZBIN:
  357.         Rxframeind = ZBIN;  Crc32 = FALSE;
  358.         c =  zrbhdr(hdr);
  359.         break;
  360.     case ZBIN32:
  361.         Crc32 = Rxframeind = ZBIN32;
  362.         c =  zrbhdr32(hdr);
  363.         break;
  364.     case ZHEX:
  365.         Rxframeind = ZHEX;  Crc32 = FALSE;
  366.         c =  zrhhdr(hdr);
  367.         break;
  368.     case CAN:
  369.         if (--cancount <= 0) {
  370.             c = ZCAN; goto fifi;
  371.         }
  372.         goto agn2;
  373.     default:
  374.         goto agn2;
  375.     }
  376.     Rxpos = hdr[ZP3] & 0377;
  377.     Rxpos = (Rxpos<<8) + (hdr[ZP2] & 0377);
  378.     Rxpos = (Rxpos<<8) + (hdr[ZP1] & 0377);
  379.     Rxpos = (Rxpos<<8) + (hdr[ZP0] & 0377);
  380. fifi:
  381. cancount=c;
  382.     switch (c) {
  383.     case GOTCAN:
  384.         c = ZCAN;
  385.     /* **** FALL THRU TO **** */
  386.     case ZNAK:
  387.     case ZCAN:
  388.     case ERROR:
  389.     case TIMEOUT:
  390.     case RCDO:
  391.         zperr("ZMODEM: Got %s %s", frametypes[c+FTOFFSET],
  392.           (c >= 0) ? "header" : "error");
  393.     /* **** FALL THRU TO **** */
  394.     default:
  395.         if (c >= -3 && c <= FRTYPES)
  396.             vfile("zgethdr: %s %lx", frametypes[c+FTOFFSET], Rxpos);
  397.         else
  398.             vfile("zgethdr: %d %lx", c, Rxpos);
  399.     }
  400. if (cancount != c)
  401.     zperr("zgethdr c=%d cancount=%d", c, cancount);
  402.     return c;
  403. }
  404.  
  405. /* Receive a binary style header (type and position) */
  406. zrbhdr(hdr)
  407. register char *hdr;
  408. {
  409.     register c, n;
  410.     register unsigned short crc;
  411.  
  412.     if ((c = zdlread()) & ~0377)
  413.         return c;
  414.     Rxtype = c;
  415.     crc = updcrc(c, 0);
  416.  
  417.     for (n=4; --n >= 0; ++hdr) {
  418.         if ((c = zdlread()) & ~0377)
  419.             return c;
  420.         crc = updcrc(c, crc);
  421.         *hdr = c;
  422.     }
  423.     if ((c = zdlread()) & ~0377)
  424.         return c;
  425.     crc = updcrc(c, crc);
  426.     if ((c = zdlread()) & ~0377)
  427.         return c;
  428.     crc = updcrc(c, crc);
  429.     if (crc & 0xFFFF) {
  430.         zperr("Bad Header CRC"); return ERROR;
  431.     }
  432.     Zmodem = 1;
  433.     return Rxtype;
  434. }
  435.  
  436. /* Receive a binary style header (type and position) with 32 bit FCS */
  437. zrbhdr32(hdr)
  438. register char *hdr;
  439. {
  440.     register c, n;
  441.     register long crc;
  442.  
  443.     if ((c = zdlread()) & ~0377)
  444.         return c;
  445.     Rxtype = c;
  446.     crc = 0xFFFFFFFFL; crc = UPDC32(c, crc);
  447. #ifdef DEBUGZ
  448.     vfile("zrbhdr32 c=%X  crc=%lX", c, crc);
  449. #endif
  450.  
  451.     for (n=4; --n >= 0; ++hdr) {
  452.         if ((c = zdlread()) & ~0377)
  453.             return c;
  454.         crc = UPDC32(c, crc);
  455.         *hdr = c;
  456. #ifdef DEBUGZ
  457.         vfile("zrbhdr32 c=%X  crc=%lX", c, crc);
  458. #endif
  459.     }
  460.     for (n=4; --n >= 0;) {
  461.         if ((c = zdlread()) & ~0377)
  462.             return c;
  463.         crc = UPDC32(c, crc);
  464. #ifdef DEBUGZ
  465.         vfile("zrbhdr32 c=%X  crc=%lX", c, crc);
  466. #endif
  467.     }
  468.     if (crc != 0xDEBB20E3) {
  469.         zperr("Bad Header CRC %lX", crc); return ERROR;
  470.     }
  471.     Zmodem = 1;
  472.     return Rxtype;
  473. }
  474.  
  475.  
  476. /* Receive a hex style header (type and position) */
  477. zrhhdr(hdr)
  478. char *hdr;
  479. {
  480.     register c;
  481.     register unsigned short crc;
  482.     register n;
  483.  
  484.     if ((c = zgethex()) < 0)
  485.         return c;
  486.     Rxtype = c;
  487.     crc = updcrc(c, 0);
  488.  
  489.     for (n=4; --n >= 0; ++hdr) {
  490.         if ((c = zgethex()) < 0)
  491.             return c;
  492.         crc = updcrc(c, crc);
  493.         *hdr = c;
  494.     }
  495.     if ((c = zgethex()) < 0)
  496.         return c;
  497.     crc = updcrc(c, crc);
  498.     if ((c = zgethex()) < 0)
  499.         return c;
  500.     crc = updcrc(c, crc);
  501.     if (crc & 0xFFFF) {
  502.         zperr("Bad Header CRC"); return ERROR;
  503.     }
  504.     if (readline(1) == '\r')    /* Throw away possible cr/lf */
  505.         readline(1);
  506.     Zmodem = 1; return Rxtype;
  507. }
  508.  
  509. /* Send a byte as two hex digits */
  510. zputhex(c)
  511. register c;
  512. {
  513.     static char    digits[]    = "0123456789abcdef";
  514.  
  515.     if (Verbose>4)
  516.         vfile("zputhex: %02X", c);
  517.     sendline(digits[(c&0xF0)>>4]);
  518.     sendline(digits[(c)&0xF]);
  519. }
  520.  
  521. /*
  522.  * Send character c with ZMODEM escape sequence encoding.
  523.  *  Escape XON, XOFF. Escape CR following @ (Telenet net escape)
  524.  */
  525. zsendline(c)
  526. register c;
  527. {
  528.     static lastsent;
  529.  
  530.     switch (c &= 0377) {
  531.     case ZDLE:
  532.         xsendline(ZDLE);
  533.         xsendline (lastsent = (c ^= 0100));
  534.         break;
  535.     case 015:
  536.     case 0215:
  537.         if (!Zctlesc && (lastsent & 0177) != '@')
  538.             goto sendit;
  539.     /* **** FALL THRU TO **** */
  540.     case 020:
  541.     case 021:
  542.     case 023:
  543.     case 0220:
  544.     case 0221:
  545.     case 0223:
  546.         xsendline(ZDLE);
  547.         c ^= 0100;
  548. sendit:
  549.         xsendline(lastsent = c);
  550.         break;
  551.     default:
  552.         if (Zctlesc && ! (c & 0140)) {
  553.             xsendline(ZDLE);
  554.             c ^= 0100;
  555.         }
  556.         xsendline(lastsent = c);
  557.     }
  558. }
  559.  
  560. /* Decode two lower case hex digits into an 8 bit byte value */
  561. zgethex()
  562. {
  563.     register c;
  564.  
  565.     c = zgeth1();
  566.     if (Verbose>4)
  567.         vfile("zgethex: %02X", c);
  568.     return c;
  569. }
  570. zgeth1()
  571. {
  572.     register c, n;
  573.  
  574.     if ((c = noxrd7()) < 0)
  575.         return c;
  576.     n = c - '0';
  577.     if (n > 9)
  578.         n -= ('a' - ':');
  579.     if (n & ~0xF)
  580.         return ERROR;
  581.     if ((c = noxrd7()) < 0)
  582.         return c;
  583.     c -= '0';
  584.     if (c > 9)
  585.         c -= ('a' - ':');
  586.     if (c & ~0xF)
  587.         return ERROR;
  588.     c += (n<<4);
  589.     return c;
  590. }
  591.  
  592. /*
  593.  * Read a byte, checking for ZMODEM escape encoding
  594.  *  including CAN*5 which represents a quick abort
  595.  */
  596. zdlread()
  597. {
  598.     register c;
  599.  
  600. again:
  601.     switch (c = readline(Rxtimeout)) {
  602.     case ZDLE:
  603.         break;
  604.     case 020:
  605.     case 021:
  606.     case 023:
  607.     case 0220:
  608.     case 0221:
  609.     case 0223:
  610.         goto again;
  611.     default:
  612.         if (Zctlesc && !(c & 0140)) {
  613.             goto again;
  614.         }
  615.         return c;
  616.     }
  617. again2:
  618.     if ((c = readline(Rxtimeout)) < 0)
  619.         return c;
  620.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  621.         return c;
  622.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  623.         return c;
  624.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  625.         return c;
  626.     switch (c) {
  627.     case CAN:
  628.         return GOTCAN;
  629.     case ZCRCE:
  630.     case ZCRCG:
  631.     case ZCRCQ:
  632.     case ZCRCW:
  633.         return (c | GOTOR);
  634.     case ZRUB0:
  635.         return 0177;
  636.     case ZRUB1:
  637.         return 0377;
  638.     case 020:
  639.     case 021:
  640.     case 023:
  641.     case 0220:
  642.     case 0221:
  643.     case 0223:
  644.         goto again2;
  645.     default:
  646.         if (Zctlesc && ! (c & 0140)) {
  647.             goto again2;
  648.         }
  649.         if ((c & 0140) ==  0100)
  650.             return (c ^ 0100);
  651.         break;
  652.     }
  653.     zperr("Got bad ZMODEM escape sequence %x", c);
  654.     return ERROR;
  655. }
  656.  
  657. /*
  658.  * Read a character from the modem line with timeout.
  659.  *  Eat parity, XON and XOFF characters.
  660.  */
  661. noxrd7()
  662. {
  663.     register c;
  664.  
  665.     for (;;) {
  666.         if ((c = readline(Rxtimeout)) < 0)
  667.             return c;
  668.         switch (c &= 0177) {
  669.         case XON:
  670.         case XOFF:
  671.             continue;
  672.         default:
  673.             if (Zctlesc && !(c & 0140))
  674.                 continue;
  675.         case '\r':
  676.         case '\n':
  677.         case ZDLE:
  678.             return c;
  679.         }
  680.     }
  681. }
  682.  
  683. /* Store long integer pos in Txhdr */
  684. stohdr(pos)
  685. long pos;
  686. {
  687.     Txhdr[ZP0] = pos;
  688.     Txhdr[ZP1] = pos>>8;
  689.     Txhdr[ZP2] = pos>>16;
  690.     Txhdr[ZP3] = pos>>24;
  691. }
  692.  
  693. /* Recover a long integer from a header */
  694. long
  695. rclhdr(hdr)
  696. register char *hdr;
  697. {
  698.     register long l;
  699.  
  700.     l = (hdr[ZP3] & 0377);
  701.     l = (l << 8) | (hdr[ZP2] & 0377);
  702.     l = (l << 8) | (hdr[ZP1] & 0377);
  703.     l = (l << 8) | (hdr[ZP0] & 0377);
  704.     return l;
  705. }
  706.  
  707. /* End of zm.c */
  708.